/**
 * Created on [2019/5/5 11:13] by 李瑞益
 * <p>
 * 项目名称: gaia-core
 * <p>
 * 本程序版权属于福建慧政通信息科技有限公司所有。
 * 任何组织和个人未经福建慧政通信息科技有限公司许可与授权,不得擅自传播、复制、更改该程序的内容。
 * 本程序受版权法和国际条约的保护。如未经授权而擅自复制或传播本程序(或其中任何部分),
 * 将受到严厉的刑事及民事制裁，并将在法律许可的范围内受到最大可能的起诉!
 * <p>
 * 2019 福建慧政通信息科技有限公司
 */

package com.lry.util;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.springframework.core.io.ClassPathResource;

/**
 * word模板替换
 *
 * @author 李瑞益
 */
@SuppressWarnings("all")
public class ReplaceWordUtil {

    /**对应文档中的变量名前缀:如<<name>>中的“<<”</>*/
    public static String prefix = "«";

    /**对应文档中的变量名后缀:如<<name>>中的“>>”*/
    public static String suffix = "»";

    /**
     * 传入模板文件路径和待替换的键值，获取替换完成后的二进制数据
     *
     * @param readFilePath 文件读取路径
     * @param replaceWord 待替换的键值
     * @return 输出流
     */
    public static OutputStream getReplaceData(Map<String, String> replaceWord, String readFilePath) {
        File file = new File(readFilePath);
        return getReplaceData(replaceWord, file);
    }

    public static OutputStream getReplaceData(Map<String, String> replaceWord, File readFile) {
        ByteArrayOutputStream os = null;
        try {
            XWPFDocument document = new XWPFDocument(new BufferedInputStream(new FileInputStream(readFile)));
            //            XWPFDocument document = new XWPFDocument(XWPFDocument.openPackage(readFilePath));
            //遍历并替换文档中的值
            iterParagraphAndReplaceVariable(document, replaceWord);
            os = new ByteArrayOutputStream();
            document.write(os);
            return os;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 设置key为word中待替换的单纯
     *
     * 传入遍历集合，设置变量名和文档中对应;如：key=companyName -》 key=《companyName》
     * 但是已在比对中增加了前后缀，所以这个方法暂时不被使用
     * @param map 参数集
     * @param prefix key的前缀
     * @param suffix key的后缀
     * @return key(与Word中待替换的单词所对应的单词)：value
     */
    public static Map<String, String> setVariableName(Map<String, String> map, String prefix, String suffix) {
        Iterator<String> keyIter = map.keySet().iterator();
        Map<String, String> newMap = new HashMap<>();
        while (keyIter.hasNext()) {
            String key = keyIter.next();
            newMap.put(prefix + key + suffix, map.get(key));
        }
        return newMap;
    }

    /**
     *传入文件对象和参数列表进行遍历
     * @param document docx文件的根
     * @param params 变量参数
     */
    private static void iterParagraphAndReplaceVariable(XWPFDocument document, Map<String, String> params) {
        //遍历段落
        Iterator<XWPFParagraph> paragraphsIterator = document.getParagraphsIterator();//获取的段落的迭代器
        while (paragraphsIterator.hasNext()) {
            XWPFParagraph paragraph = paragraphsIterator.next();
            //替换段落里的变量
            replaceVariable(paragraph, params);
        }
        //遍历表格
        Iterator<XWPFTable> tablesIterator = document.getTablesIterator();
        while (tablesIterator.hasNext()) {
            XWPFTable table = tablesIterator.next();
            replaceVariable(table, params);
        }
    }

    /**
     * 传入段落对象 比对替换
     * 1、遍历文本区域
     * 2、遍历参数列表
     * 3、比对
     * @param paragraph 段落
     * @param params 待替换键值
     */
    public static void replaceVariable(XWPFParagraph paragraph, Map<String, String> params) {
        //文本区域
        List<XWPFRun> runList = paragraph.getRuns();
        Iterator<String> iter = params.keySet().iterator();
        //遍历遍历参数
        while (iter.hasNext()) {
            String key = iter.next();//变量名
            //遍历文本区域
            for (int i = 0; i < runList.size(); i++) {
                if (runList.get(i).getText(runList.get(i).getTextPosition()) != null &&
                    runList.get(i).getText(runList.get(i).getTextPosition())
                           .equalsIgnoreCase(key)) {
                    //从0开始替换变量
                    runList.get(i).setText(params.get(key).toString(), 0);
                }
            }
        }
    }

    /**
     * 传入表格对象 比对替换
     * 1、遍历表格行
     * 2、遍历行的单元格
     * 3、比对
     * @param table 表格对象
     * @param params 待替换键值
     */
    public static void replaceVariable(XWPFTable table, Map<String, String> params) {
        List<XWPFTableRow> rows = table.getRows();
        //遍历行
        for (XWPFTableRow row : rows) {
            List<XWPFTableCell> cells = row.getTableCells();
            //遍历单元格
            for (XWPFTableCell cell : cells) {
                List<XWPFParagraph> paragraphs = cell.getParagraphs();
                //遍历单元格里的段落
                for (XWPFParagraph paragraph : paragraphs) {
                    replaceVariable(paragraph, params);
                }
            }
        }
    }

    //    @Test
    public void repleace() throws IOException {
        //变量
        Map<String, String> map = new HashMap<>();
        map.put("CompanyName", "瑞益有限责任公司");
        map.put("Type", "计算机");
        map.put("Number", "05120213A");

        org.springframework.core.io.Resource resource = new ClassPathResource("files/审查意见书.docx");
        File sourceFile = resource.getFile();
        File writeFile = new File(sourceFile.getParent());
        System.out.println(writeFile);
        ReplaceWordUtil.setVariableName(map, ReplaceWordUtil.prefix, ReplaceWordUtil.suffix);
        ByteArrayOutputStream os = (ByteArrayOutputStream) ReplaceWordUtil.getReplaceData(map, sourceFile);
        OutputStream oss = new FileOutputStream("C:\\Users\\LI\\Desktop\\test-replaceword.docx");
        os.writeTo(oss);
        oss.flush();
        oss.close();

        //        String readFilePath = "D:\\ProgramData\\Gitee Pro\\poiextended\\src\\main\\resources\\不予受理通知书.docx";
        //        String writeFilePath ="D:\\ProgramData\\Gitee Pro\\poiextended\\src\\main\\resources\\completeword
        //        .docx";
        //        replaceOperation(readFilePath,writeFilePath,map);
        //        byte[] data = getReplaceData(readFilePath, map);
        //        System.out.println(Arrays.toString(data));
    }
}
